package com.learn.io.netty;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author wangxing
 * @version 2020/7/30 15:39 Administrator
 */
public class CharNettyServerHandler extends SimpleChannelInboundHandler<String> {
    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    Logger logger = LoggerFactory.getLogger(MyNettyServerHandler.class);

    /**
     * Calls {@link ChannelHandlerContext#fireChannelActive()} to forward
     * to the next { ChannelInboundHandler} in the { ChannelPipeline}.
     * <p>
     * Sub-classes may override this method to change behavior.
     *
     * @param ctx
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("服务端读取线程name:{},id:{}", Thread.currentThread().getName(), Thread.currentThread().getId());
        Channel channel = ctx.channel();
        channelGroup.writeAndFlush("[客户端"+channel.remoteAddress()+"]上线了");
        channelGroup.add(channel);
        logger.info("--------------[客户端{}]上线了-----------", channel.remoteAddress());
    }

    /**
     * Calls {@link ChannelHandlerContext#fireChannelInactive()} to forward
     * to the next {ChannelInboundHandler} in the {ChannelPipeline}.
     * <p>
     * Sub-classes may override this method to change behavior.
     *
     * @param ctx
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        channelGroup.writeAndFlush("[客户端"+channel.remoteAddress()+"]下线了");
    }

    /**
     * <strong>Please keep in mind that this method will be renamed to
     * {@code messageReceived(ChannelHandlerContext, I)} in 5.0.</strong>
     * <p>
     * Is called for each message of type I.
     *
     * @param ctx the {@link ChannelHandlerContext} which this {@link SimpleChannelInboundHandler}
     *            belongs to
     * @param msg the message to handle
     * @throws Exception is thrown if an error occurred
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        Channel channel = ctx.channel();
//        消息格式msg=msgType/ipPort/msgData
        String[]msgs = msg.split("/");
//        one
        String msgType="all";
        String ipPort="";
        if(msgs.length>=3){
            msgType = msgs[0];
            if("one".equals(msgType)){
                ipPort = "/"+msgs[1];
            }
        }
        String finalIpPort = ipPort;
        String finalMsgType = msgType;
        channelGroup.forEach(ch -> {
            runMethod(finalMsgType, channel, msg, ch, finalIpPort);
        });
    }
    private void runMethod(String finalMsgType,Channel myChannel,String msg,Channel ch,String finalIpPort){
        if("all".equals(finalMsgType)){
            if (ch != myChannel) {
                ch.writeAndFlush("[客户端" + myChannel.remoteAddress() + "],发送了消息" + msg);
            } else {
                ch.writeAndFlush("[我自己],发送了消息" + msg);
            }
        }else {
            logger.info("ch.localAddress():{}----ch.remoteAddress():{}------finalIpPort:{}",ch.localAddress(),ch.remoteAddress(),finalIpPort);
            String remoteAddress =ch.remoteAddress().toString();
            System.out.println(remoteAddress);
            if(finalIpPort.equals(remoteAddress)){
                logger.info("send message to {}",ch.remoteAddress());
                ch.writeAndFlush("[客户端" + myChannel.remoteAddress() + "],发送了消息" + msg);
            }
        }
    }

    /**
     * Calls {@link ChannelHandlerContext#fireExceptionCaught(Throwable)} to forward
     * to the next { ChannelHandler} in the { ChannelPipeline}.
     * <p>
     * Sub-classes may override this method to change behavior.
     *
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
